/* * Copyright 2013-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package org.springframework.cloud.bus; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import javax.annotation.PostConstruct; import org.junit.After; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; import org.springframework.cloud.bus.event.AckRemoteApplicationEvent; import org.springframework.cloud.bus.event.RefreshRemoteApplicationEvent; import org.springframework.cloud.bus.event.SentApplicationEvent; import org.springframework.cloud.stream.annotation.Output; import org.springframework.cloud.stream.test.binder.TestSupportBinderAutoConfiguration; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.context.event.EventListener; import org.springframework.integration.annotation.MessageEndpoint; import org.springframework.integration.annotation.ServiceActivator; import org.springframework.integration.channel.DirectChannel; import org.springframework.messaging.Message; import org.springframework.messaging.MessageChannel; import org.springframework.messaging.support.ChannelInterceptor; import org.springframework.messaging.support.ChannelInterceptorAdapter; import org.springframework.messaging.support.GenericMessage; public class BusAutoConfigurationTests { private ConfigurableApplicationContext context; @After public void close() { if (this.context != null) { this.context.close(); } } @Test public void inboundNotForSelf() { this.context = SpringApplication.run(InboundMessageHandlerConfiguration.class); this.context.setId("foo"); this.context.getBean(SpringCloudBusClient.INPUT, MessageChannel.class) .send(new GenericMessage<>( new RefreshRemoteApplicationEvent(this, "bar", "bar"))); assertNull( this.context.getBean(InboundMessageHandlerConfiguration.class).refresh); } @Test public void inboundFromSelf() { this.context = SpringApplication.run(InboundMessageHandlerConfiguration.class); this.context.setId("foo"); this.context.getBean(SpringCloudBusClient.INPUT, MessageChannel.class) .send(new GenericMessage<>( new RefreshRemoteApplicationEvent(this, "foo", null))); assertNull( this.context.getBean(InboundMessageHandlerConfiguration.class).refresh); } @Test public void inboundNotFromSelf() { this.context = SpringApplication.run(InboundMessageHandlerConfiguration.class); this.context.setId("bar"); this.context.getBean(SpringCloudBusClient.INPUT, MessageChannel.class) .send(new GenericMessage<>( new RefreshRemoteApplicationEvent(this, "foo", null))); assertNotNull( this.context.getBean(InboundMessageHandlerConfiguration.class).refresh); } @Test public void inboundNotFromSelfWithAck() throws Exception { this.context = SpringApplication .run(new Object[] { InboundMessageHandlerConfiguration.class, OutboundMessageHandlerConfiguration.class, SentMessageConfiguration.class }, new String[] {}); this.context.setId("bar"); this.context.getBean(SpringCloudBusClient.INPUT, MessageChannel.class) .send(new GenericMessage<>( new RefreshRemoteApplicationEvent(this, "foo", null))); RefreshRemoteApplicationEvent refresh = this.context .getBean(InboundMessageHandlerConfiguration.class).refresh; assertNotNull(refresh); OutboundMessageHandlerConfiguration outbound = this.context .getBean(OutboundMessageHandlerConfiguration.class); outbound.latch.await(2000L, TimeUnit.MILLISECONDS); String message = (String) outbound.message.getPayload(); assertTrue("Wrong ackId: " + message, message.contains("\"ackId\":\"" + refresh.getId())); } @Test public void inboundNotFromSelfWithTrace() throws Exception { this.context = SpringApplication.run( new Object[] { InboundMessageHandlerConfiguration.class, OutboundMessageHandlerConfiguration.class, SentMessageConfiguration.class }, new String[] { "--spring.cloud.bus.trace.enabled=true" }); this.context.setId("bar"); this.context.getBean(SpringCloudBusClient.INPUT, MessageChannel.class) .send(new GenericMessage<>( new RefreshRemoteApplicationEvent(this, "foo", null))); RefreshRemoteApplicationEvent refresh = this.context .getBean(InboundMessageHandlerConfiguration.class).refresh; assertNotNull(refresh); SentMessageConfiguration sent = this.context .getBean(SentMessageConfiguration.class); assertNotNull(sent.event); assertEquals(1, sent.count); } @Test public void inboundAckWithTrace() throws Exception { this.context = SpringApplication.run( new Object[] { InboundMessageHandlerConfiguration.class, OutboundMessageHandlerConfiguration.class, AckMessageConfiguration.class }, new String[] { "--spring.cloud.bus.trace.enabled=true" }); this.context.setId("bar"); this.context.getBean(SpringCloudBusClient.INPUT, MessageChannel.class) .send(new GenericMessage<>(new AckRemoteApplicationEvent(this, "foo", null, "ID", "bar", RefreshRemoteApplicationEvent.class))); AckMessageConfiguration sent = this.context .getBean(AckMessageConfiguration.class); assertNotNull(sent.event); assertEquals(1, sent.count); } @Test public void outboundFromSelf() throws Exception { this.context = SpringApplication.run(OutboundMessageHandlerConfiguration.class, "--debug=true"); this.context.setId("foo"); this.context.publishEvent(new RefreshRemoteApplicationEvent(this, "foo", null)); OutboundMessageHandlerConfiguration outbound = this.context .getBean(OutboundMessageHandlerConfiguration.class); outbound.latch.await(2000L, TimeUnit.MILLISECONDS); assertNotNull(outbound.message); } @Test public void outboundNotFromSelf() { this.context = SpringApplication.run(OutboundMessageHandlerConfiguration.class); this.context.setId("bar"); this.context.publishEvent(new RefreshRemoteApplicationEvent(this, "foo", null)); assertNull( this.context.getBean(OutboundMessageHandlerConfiguration.class).message); } @Test public void inboundNotFromSelfPathPattern() { this.context = SpringApplication.run(InboundMessageHandlerConfiguration.class); this.context.setId("bar:1000"); this.context.getBean(SpringCloudBusClient.INPUT, MessageChannel.class) .send(new GenericMessage<>( new RefreshRemoteApplicationEvent(this, "foo", "bar:*"))); assertNotNull( this.context.getBean(InboundMessageHandlerConfiguration.class).refresh); } @Test public void inboundNotFromSelfDeepPathPattern() { this.context = SpringApplication.run(InboundMessageHandlerConfiguration.class); this.context.setId("bar:test:1000"); this.context.getBean(SpringCloudBusClient.INPUT, MessageChannel.class) .send(new GenericMessage<>( new RefreshRemoteApplicationEvent(this, "foo", "bar:**"))); assertNotNull( this.context.getBean(InboundMessageHandlerConfiguration.class).refresh); } @Test public void inboundNotFromSelfFlatPattern() { this.context = SpringApplication.run(InboundMessageHandlerConfiguration.class); this.context.setId("bar"); this.context.getBean(SpringCloudBusClient.INPUT, MessageChannel.class) .send(new GenericMessage<>( new RefreshRemoteApplicationEvent(this, "foo", "bar*"))); assertNotNull( this.context.getBean(InboundMessageHandlerConfiguration.class).refresh); } @Configuration @Import({ MessageConsumer.class, BusAutoConfiguration.class, TestSupportBinderAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class }) protected static class OutboundMessageHandlerConfiguration { @Autowired @Output(SpringCloudBusClient.OUTPUT) private MessageChannel cloudBusOutboundChannel; private CountDownLatch latch = new CountDownLatch(1); private Message<?> message; @PostConstruct public void init() { ((DirectChannel) this.cloudBusOutboundChannel).addInterceptor(interceptor()); } private ChannelInterceptor interceptor() { return new ChannelInterceptorAdapter() { @Override public void postSend(Message<?> message, MessageChannel channel, boolean sent) { OutboundMessageHandlerConfiguration.this.message = message; OutboundMessageHandlerConfiguration.this.latch.countDown(); } }; } } @Configuration @MessageEndpoint protected static class MessageConsumer { @ServiceActivator(inputChannel = SpringCloudBusClient.OUTPUT) public void handle(Message<?> msg) { } } @Configuration @Import({ MessageConsumer.class, BusAutoConfiguration.class, TestSupportBinderAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class }) protected static class InboundMessageHandlerConfiguration { private RefreshRemoteApplicationEvent refresh; @EventListener(RefreshRemoteApplicationEvent.class) public void refresh(RefreshRemoteApplicationEvent event) { this.refresh = event; } } @Configuration protected static class SentMessageConfiguration { private SentApplicationEvent event; private int count; @EventListener public void onSend(SentApplicationEvent event) { this.event = event; this.count++; } } @Configuration protected static class AckMessageConfiguration { private AckRemoteApplicationEvent event; private int count; @EventListener public void onSend(AckRemoteApplicationEvent event) { this.event = event; this.count++; } } }